#include "sqlist.h"

/**
 * @brief 内部辅助函数，检查并按需扩充容量
 * @note 假定在调用此函数之前已经获取了互斥锁
 * @param sl 指向顺序表结构体的指针
 */
static void SeqList_CheckCapacity(SeqList_t *sl)
{
    assert(sl); // 确保 sl 指针不为 NULL

    if (sl->size >= sl->capacity)
    {
        // 容量翻倍
        size_t new_capacity = sl->capacity == 0 ? 10 : sl->capacity * 2;
        size_t new_size_bytes = new_capacity * sl->element_size;

        // 使用 FreeRTOS 的内存分配函数
        void *tmp = pvPortMalloc(new_size_bytes);

        if (tmp != NULL)
        {
            // 如果存在旧数据，将其复制到新内存中
            if (sl->data != NULL)
            {
                memcpy(tmp, sl->data, sl->size * sl->element_size);
                vPortFree(sl->data);
            }
            sl->data = tmp;
            sl->capacity = new_capacity;
        }
        else
        {
            // 处理内存分配失败。在实际应用中，应更优雅地处理此错误。
            printf("Error: Failed to reallocate memory for SeqList.\n");
        }
    }
}

/**
 * @brief 初始化顺序表
 * @param sl 指向顺序表结构体的指针
 * @param element_size 元素大小（字节）
 * @return pdPASS 表示初始化成功，pdFAIL 表示失败
 */
BaseType_t SeqList_Init(SeqList_t *sl, size_t element_size)
{
    assert(sl);
    assert(element_size > 0);

    sl->size = 0;
    sl->capacity = 10; // 初始容量
    sl->element_size = element_size;
    sl->data = pvPortMalloc(sl->capacity * sl->element_size);

    if (sl->data == NULL) {
        // 初始内存分配失败
        return pdFAIL;
    }

    sl->mutex = xSemaphoreCreateMutex();
    if (sl->mutex == NULL) {
        // 创建互斥锁失败，释放已分配的内存
        vPortFree(sl->data);
        sl->data = NULL;
        return pdFAIL;
    }

    return pdPASS;
}

/**
 * @brief 销毁顺序表，释放其占用的资源
 * @param sl 指向顺序表结构体的指针
 */
void SeqList_Destory(SeqList_t *sl)
{
    assert(sl);
    // 获取互斥锁以安全地销毁列表
    if (xSemaphoreTake(sl->mutex, portMAX_DELAY) == pdTRUE)
    {
        if (sl->data != NULL) {
            vPortFree(sl->data);
            sl->data = NULL;
        }
        sl->capacity = sl->size = 0;

        // 删除互斥锁
        vSemaphoreDelete(sl->mutex);
        sl->mutex = NULL; // 防止悬挂指针
    }
}

/**
 * @brief 在顺序表尾部插入一个元素
 * @param sl 指向顺序表结构体的指针
 * @param item 指向要插入元素的指针
 */
void SeqList_PushBack(SeqList_t *sl, const void *item)
{
    assert(sl && item);
    if (xSemaphoreTake(sl->mutex, portMAX_DELAY) == pdTRUE)
    {
        SeqList_CheckCapacity(sl);

        // 计算下一个可用位置的地址
        void *dest = (char*)sl->data + (sl->size * sl->element_size);

        // 将 item 的数据复制到列表中
        memcpy(dest, item, sl->element_size);

        sl->size++;

        xSemaphoreGive(sl->mutex);
    }
}

/**
 * @brief 在顺序表头部插入一个元素
 * @param sl 指向顺序表结构体的指针
 * @param item 指向要插入元素的指针
 */
void SeqList_PushFront(SeqList_t *sl, const void *item)
{
    assert(sl && item);
    if (xSemaphoreTake(sl->mutex, portMAX_DELAY) == pdTRUE)
    {
        SeqList_CheckCapacity(sl);

        // 将所有元素向右移动一个位置，为头部腾出空间
        void* dest = (char*)sl->data + sl->element_size;
        void* src = sl->data;
        size_t bytes_to_move = sl->size * sl->element_size;
        memmove(dest, src, bytes_to_move);

        // 将新元素复制到列表头部
        memcpy(sl->data, item, sl->element_size);

        sl->size++;

        xSemaphoreGive(sl->mutex);
    }
}

/**
 * @brief 移除顺序表尾部的一个元素
 * @param sl 指向顺序表结构体的指针
 */
void SeqList_PopBack(SeqList_t *sl)
{
    assert(sl);
    if (xSemaphoreTake(sl->mutex, portMAX_DELAY) == pdTRUE)
    {
        if (sl->size > 0)
        {
            sl->size--;
        }
        xSemaphoreGive(sl->mutex);
    }
}

/**
 * @brief 移除顺序表头部的一个元素
 * @param sl 指向顺序表结构体的指针
 */
void SeqList_PopFront(SeqList_t *sl)
{
    assert(sl);
    if (xSemaphoreTake(sl->mutex, portMAX_DELAY) == pdTRUE)
    {
        if (sl->size > 0)
        {
            // 将所有元素向左移动一个位置
            void* dest = sl->data;
            void* src = (char*)sl->data + sl->element_size;
            size_t bytes_to_move = (sl->size - 1) * sl->element_size;
            memmove(dest, src, bytes_to_move);

            sl->size--;
        }
        xSemaphoreGive(sl->mutex);
    }
}

/**
 * @brief 打印顺序表中的所有元素
 * @param sl 指向顺序表结构体的指针
 * @param print_func 用于打印单个元素的回调函数指针
 */
void SeqList_Print(const SeqList_t *sl, void (*print_func)(const void *item))
{
    assert(sl && print_func);
    if (xSemaphoreTake(sl->mutex, portMAX_DELAY) == pdTRUE)
    {
        printf("SeqList (Size: %zu, Capacity: %zu): [ ", sl->size, sl->capacity); 
        for (size_t i = 0; i < sl->size; ++i)
        {
            // 计算第 i 个元素的地址并调用打印函数
            const void *item = (const char*)sl->data + (i * sl->element_size);
            print_func(item);
        }
        printf("]\n");

        xSemaphoreGive(sl->mutex);
    }
}

/**
 * @brief 获取顺序表中指定索引处的元素
 * @param sl 指向顺序表结构体的指针
 * @param index 要访问的元素索引
 * @param out_item 用于接收元素数据的缓冲区指针
 * @return pdPASS 表示获取成功，pdFAIL 表示失败
 */
BaseType_t SeqList_Get(const SeqList_t *sl, size_t index, void *out_item)
{
    assert(sl && out_item);
    assert(index < sl->size);

    if (xSemaphoreTake(sl->mutex, portMAX_DELAY) == pdTRUE) {
        const char *src = (const char*)sl->data + index * sl->element_size;
        memcpy(out_item, src, sl->element_size);
        xSemaphoreGive(sl->mutex);
        return pdPASS;
    }
    return pdFAIL;
}

BaseType_t SeqList_Get_Size(const SeqList_t *sl,uint8_t *size)
{
    assert(sl);

    if (xSemaphoreTake(sl->mutex, portMAX_DELAY) == pdTRUE) {
        *size=sl->size;
        xSemaphoreGive(sl->mutex);
        return pdPASS;
    }
    return pdFAIL;
}
